/**
 * 
 */
package com.hurr.assembler;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;

import com.hurr.bo.AbstractModel;
import com.hurr.dto.AbstractModelDto;

/**
 * This static class uses models objects with data transfer objects or Dto,
 * using reflection
 * 
 * @author Fernando Perelli
 * 
 */
public final class Assembler {

	/**
	 * The constant Assembly
	 */
	private static final String ASSEMBLY = "Assembly";
	/**
	 * The constant ToDto
	 */
	private static final String TO_DTO = "toDto";
	/**
	 * The constant ToModel
	 */
	private static final String TO_MODEL = "toModel";
	/**
	 * The constant ToDtos
	 */
	private static final String TO_DTOS = "toDtos";
	/**
	 * The constant ToModels
	 */
	private static final String TO_MODELS = "toModels";
	/**
	 * @param a model
	 * @return a dto 
	 * @throws ClassNotFoundException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 */
	public static AbstractModelDto toDto(AbstractModel model)
			throws ClassNotFoundException, NoSuchMethodException,
			SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		
		Class<?> myClass = Class.forName(model.getClass().getName() + ASSEMBLY);
		Object classInvoke = myClass.newInstance();
		Method method = myClass.getMethod(TO_DTO, myClass.getClass());
		return ( AbstractModelDto) method.invoke(classInvoke, model);
	}
	
	/**
	 * @param a dto
	 * @return a model 
	 * @throws ClassNotFoundException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 */
	public static AbstractModel toModel(AbstractModelDto dto)
			throws ClassNotFoundException, NoSuchMethodException,
			SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		
		String className = dto.getClass().getName();
		Class<?> myClass = Class.forName(className.substring(0, className.length()-4) + ASSEMBLY);
		Object classInvoke = myClass.newInstance();
		Method method = myClass.getMethod(TO_MODEL, myClass.getClass());
		return (AbstractModel) method.invoke(classInvoke, dto);
	}

	
	/**
	 * @param a models
	 * @return a dtos 
	 * @throws ClassNotFoundException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 */
	@SuppressWarnings("unchecked")
	public static Collection<? extends AbstractModelDto> toDtos(Collection<? extends AbstractModel> models)
			throws ClassNotFoundException, NoSuchMethodException,
			SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		
		Class<?> myClass = Class.forName(models.getClass().getName() + ASSEMBLY);
		Object classInvoke = myClass.newInstance();
		Method method = myClass.getMethod(TO_DTOS, myClass.getClass());
		return (Collection<? extends AbstractModelDto>) method.invoke(classInvoke, models);
	}

	/**
	 * @param a dtos
	 * @return a models
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws ClassNotFoundException
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	@SuppressWarnings("unchecked")
	public static Collection<? extends AbstractModel> toModels(Collection<? extends AbstractModelDto> dtos) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		Class<?> myClass = Class.forName(dtos.getClass().getName() + ASSEMBLY);
		Object classInvoke = myClass.newInstance();
		Method method = myClass.getMethod(TO_MODELS, myClass.getClass());
		return (Collection<? extends AbstractModel>) method.invoke(classInvoke, dtos);
	}
	
}
